mod trait_sample;
pub use crate::trait_sample::*;
//范型结构体
struct Point<T> {
    x: T,
    y: T,
}
// 范型结构体的方法
impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }

    fn y(&self) -> &T {
        &self.y
    }
}
//针对具体范型的实例的类型实现方法
impl Point<f32> {
    // 泛型方法
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

struct Point2<T, U> {
    x: T,
    y: U,
}

impl<T, U> Point2<T, U> {
    // 泛型方法,注意里面的范型参数对应关系
    // T U 对应于本体的 Point2<T, U>
    // V W 对应于 参数other的 Point2<V, W>
    fn mixup<V, W>(self, other: Point2<V, W>) -> Point2<T, W> {
        Point2 {
            x: self.x,
            y: other.y,
        }
        
    }
}

use std::cmp::PartialOrd;
fn largest<T: PartialOrd +Copy>(list: &[T]) -> T {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    }
    else {
        y
    }
}

fn longest2<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    }
    else {
        y
    }
}

//可以不传引用，直接把实体传出去
fn longest3<'a>(x:&str,y:&str)->String{
    let result = String::from("long string is long");
    result
}

fn main() {
    // error 泛型的类型必须一致
    // let number_1 = Point { x: 5, y: 10.4 };
    // let number_2 = Point { x: "Hello", y: 'c' };

    let number =  Point { x: 5, y: 10 };
    
    println!("Point x: {}, y: {}", number.x, number.y);
    // 使用范型方法
    println!("Point x: {}, y: {}", number.x(), number.y());

    // Point2 用了两个泛型的类型，可以存储不同类型
    let p1 = Point2 { x: 5, y: 10.4 };

    let p2 = Point2 { x: "Hello", y: 'c' };

    println!("Point2 x: {}, y: {}", p1.x, p2.y);

    let p3 = p1.mixup(p2);

    println!("Point3 x: {}, y: {}", p3.x, p3.y);


    let number_list = vec![34, 50, 25, 100, 65];

    let result = largest(&number_list);
    println!("The largest number is {}", result);

    let char_list = vec!['y', 'm', 'a', 'q'];

    let result = largest(&char_list);
    println!("The largest char is {}", result);

    let tweet = Tweet {
        username: String::from("horse_ebooks"),
        content: String::from(
            "of course, as you probably already know, people",
        ),
        reply: false,
        retweet: false,
    };

    println!("1 new tweet: {}",tweet.summarize());

    notify(&tweet);


    let tweet = returns_summarizable();
    println!("1 new tweet: {}",tweet.summarize());

    let string1 = String::from("abcd");
    let result1;
    {
    
    let string1_2 = "xyz";
    // string1_2 是静态对象，所以string1_2 的生命周期是全局的。
    result1 = longest(string1.as_str(), string1_2);
    println!("The longest string is {}", result1);
    }
    let string2 = String::from("abcd");
    let result2;
    {
        let string2_2 = String::from("xyz");
        // 错误，因为 string2_2 的生命周期比 result2 短
        result2 = longest3(&string2, &string2_2.as_str());
    }
    println!("The longest string is {}", result2.as_str());


    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().expect("Could not find a '.'");
    let i = ImportantExcerpt { part: first_sentence };
    i.announce_and_return_part("hello");
}

struct ImportantExcerpt<'a> {
    part: &'a str,
    // &self 的生命周期是 &self.part 的生命周期
}

// 方法生命周期
impl<'a> ImportantExcerpt<'a> {
    // 返回引用的生命周期是 &self.part 的生命周期
    fn announce_and_return_part(&self, announcement: &str) -> &str {
        println!("Attention please: {}", announcement);
        self.part
        // 返回引用的生命周期是 &self.part 的生命周期，也就是 &'a str
    }
}
